classdef For < preparser.control.BaseClass
    properties
        ForBody
        DoBody
        ControlName
        Token
    end
    
    
    
    
    properties (Constant)
        CONTROL_NAME_PATTERN = '\?[^\s=!\.:;]*'
        
        FOR_PATTERN = [ ...
            '^(',preparser.control.For.CONTROL_NAME_PATTERN,')', ...
            '(\s*=)(.*)', ...
            ]
    end
    
    
    
    
    methods
        function this = For(c,sh)
            import preparser.control.*;
            import exception.Preparser;
            if nargin==0
                return
            end
            keyFor = Keyword.FOR;
            keyDo = Keyword.DO;
            this.ForBody = [ ];
            this.DoBody = [ ];
            le = cumsum(imag(sh));
            posDo = find(sh==keyDo & le==1);
            if isempty(posDo)
                return
            elseif length(posDo)>1
                throwCode(exception.Preparser.CTRL_FOR_MULTIPLE_DO, c);
            end
            c1 = c(len(keyFor)+1:posDo-1);
            sh1 = sh(len(keyFor)+1:posDo-1);
            this.ForBody = Control(c1, [ ], sh1);
            c2 = c(posDo+len(keyDo):end);
            sh2 = sh(posDo+len(keyDo):end);
            this.DoBody = Control(c2, [ ], sh2);
        end
        
        
        
        
        function c = writeFinal(this,p,varargin)
            import preparser.Preparser;
            c = '';
            if isempty(this.ForBody) || isempty(this.DoBody)
                return
            end
%             forCode = writeFinal(this.ForBody,p,varargin{:});
%             doCode = writeFinal(this.DoBody,p,varargin{:});
%             readForCode(this,forCode,p.Assigned);
%             c = replaceDoCode(this,doCode);
            
            forCode = writeFinal(this.ForBody,p,varargin{:});
            readForCode(this,forCode,p.Assigned);
            c = expandDoCode(this,p,varargin{:});
        end
        
        
        
        
        function readForCode(this,forCode,assigned)
            import preparser.control.For;
            forCode = strtrim(forCode);
            % Replace pseudosubstitutions in the for block.
            forCode = preparser.Pseudosubs.parse(forCode,assigned);
            tok = regexp(forCode,For.FOR_PATTERN,'tokens','once');
            if ~isempty(tok)
                controlName = tok{1};
                tokenCode = tok{3};
            else
                controlName = '?';
                tokenCode = forCode;
            end
            token = regexp(tokenCode,'[^\s,;]+','match');
            this.ControlName = controlName;
            this.Token = token;
        end
        
        
        
        
        function c = expandDoCode(this, p, varargin)
            import preparser.control.For;
            BR = sprintf('\n');
            c = '';
            % Remove leading and trailing line breaks.
            % doCode = regexprep(doCode,'^\s*\n','');
            % doCode = regexprep(doCode,'\n\s*$','');
            controlName = this.ControlName;
            
            for i = 1 : length(this.Token)
                p.StoreForCtrl(end+1,:) = { controlName, this.Token{i} };
                c1 = writeFinal(this.DoBody, p, varargin{:});
                c = [c, c1]; %#ok<AGROW>
                p.StoreForCtrl(end,:) = [ ];
            end
        end
    end
end
